package com.mida.app.report.service.impl;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.mida.app.report.service.DetailCodingSystemService;
import com.mida.app.report.service.DocFastWriteService;
import com.mida.app.report.utils.DocFastWriteUtil;
import com.mida.bms.report.api.DocFastWriteApi;
import com.mida.bms.report.vo.PatientInfoParameterVo;
import com.mida.dms.knw.api.KnwReportApi;
import com.mida.dms.knw.entity.vo.BodyTreeVo;
import com.mida.dms.knw.entity.vo.KnwIndividualSoltVos;
import com.mida.dms.knw.entity.vo.KnwNoumenonVo;
import com.mida.dms.knw.entity.vo.KnwSlotVo;
import com.mida.dms.knw.vo.*;
import com.mida.dms.mdm.api.provider.IResourceInfoApi;
import com.mida.dms.mdm.dto.MediaImageFindDto;
import com.mida.dms.mdm.pojo.auto.MsdDataSet;
import com.mida.dms.mdm.pojo.auto.MsdDetailCodingSystem;
import com.mida.dms.mdm.vo.provider.MediaImageResourceVo;
import com.mida.tool.common.result.BaseResult;
import com.mida.tool.common.result.ListResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 数字患者
 */
@Service
@Slf4j
@Transactional
public class DocFastWriteServiceImpl extends BaseResult implements DocFastWriteService {


    private static final String WARN_MESSAGE_0001 = "该检查部位没有注册成概念";
    private static final long RELEASE_STATUS = 43736704971964416L;
    private static final String LONG_STRING = "|";
    private static final String ERROR_MESSAGE_0001 = "部位的soid为空";
    private static final String ERROR_MESSAGE_0003 = "本体列表为空";
    private static final String COMMA = ",";


    @Autowired
    private DocFastWriteApi docFastWriteApi;

    @Autowired
    private IResourceInfoApi iResourceInfoApi;

    @Autowired
    private KnwReportApi knwReportApi;

    @Autowired
    private DetailCodingSystemService detailCodingSystemService;

    @Override
    public ListResult getDocStructTemplateList(PatientInfoParameterVo vo) throws Exception {
        // 根据当前登录用户的标识、获取模板列表
        return docFastWriteApi.getDocStructTemplateList(vo);
    }

    /**
     * 根据当前患者标识、指定报告发布状态、以及检查类型soid查询患者，历史报告记录列表
     *
     * @param vo
     * @return
     * @throws Exception
     */
    @Override
    public ListResult getHistoryReportList(PatientInfoParameterVo vo) throws Exception {
        // 指定报告发布状态
        vo.setStatus(RELEASE_STATUS);
        // 根据当前患者标识、指定报告发布状态、以及检查类型soid查询患者，历史报告记录列表
        return docFastWriteApi.getHistoryReportList(vo);
    }

    /**
     * 查询标准、精准片段
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult<KnwNoumenonVo> getKnwNoumenonVoList(KnwNoumenonPageVo vo) throws Exception {
        log.info("开始查询标准、精准片段,查询条件: " + vo.toString());
        ListResult result = new ListResult();
        StopWatch stopWatch = StopWatch.createStarted();

        List<KnwNoumenonVo> list = new ArrayList<KnwNoumenonVo>();
        try {
            // 查询标准、精准片段
            ListResult<List<KnwNoumenonVo>> listResultTmp = knwReportApi.getKnwNoumenonVoList(vo);

            if (listResultTmp != null && listResultTmp.getData() != null) {
                list = listResultTmp.getData();

                // 取得所有集值soid列表、以及编码体系soid列表
                Map<Long, Long> mapDataSetSoid = new HashMap<>();
                Map<Long, Long> mapDetailCodingSystemSoid = new HashMap<>();
                List<Long> listTmp = new ArrayList<Long>();
                // 获取值集SOID的MAP和编码体系soid的MAP
                DocFastWriteUtil.gainDsMapSoidAndDcsMapSoid(list, mapDataSetSoid, mapDetailCodingSystemSoid);
                // 根据值soid获取对应集值对象、编码体系对象并进行设置相关对象属性对应的名称
                setKnwNoumenonVoPropertyName(list, mapDataSetSoid, mapDetailCodingSystemSoid);
            }

            buildListSuccess(result, list);
        } catch (Exception e) {
            list = new ArrayList<KnwNoumenonVo>();
            log.error("查询标准、精准片段发送异常", e);
            buildListWarn(result, "查询标准、精准片段失败,请联系管理员");
        } finally {
            stopWatch.stop();
            log.info("本次查询耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }


    /**
     * 获取人体树结构根节点
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult<BodyTreeVo> getBodyRootNode(BodyTreeParameterVo vo) {
        log.info("开始查询人体树根节点,查询条件: " + vo.toString());
        ListResult result = new ListResult();
        StopWatch stopWatch = StopWatch.createStarted();

        List<BodyTreeVo> list = new ArrayList<BodyTreeVo>();
        BodyTreeVo bodyTreeVo = new BodyTreeVo();
        try {
            // 根据部位dataset值 取得注册的概念soid
            if (StringUtils.isEmpty(vo.getBodySoid())) {
                buildListWarn(result, ERROR_MESSAGE_0001);
                return result;
            }

            // 根据前端传值，根据【,】符号取得部位soid数组
            String[] strs = vo.getBodySoid().split(COMMA);
            List<Long> listConceptSoid = new ArrayList<Long>();
            Map<Long, Object> mapBodySoid = new HashMap<Long, Object>();

            // 根据检查部位下、部位soid获取对应概念soid、设置map
            gainBodyConceptSoid(strs, listConceptSoid, mapBodySoid);

            // 设置人体树结构相关属性
            setBodyTreeVo(vo, list, listConceptSoid, mapBodySoid);

            buildListSuccess(result, list);
        } catch (Exception e) {
            list = new ArrayList<BodyTreeVo>();
            log.error("人体树根节点异常" + e.getMessage(), e);
            buildListWarn(result, "查询人体树根节点失败,请联系管理员");
        } finally {
            stopWatch.stop();
            log.info("本次查询耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }


    /**
     * 获取人体部位子节点
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult<BodyTreeVo> getBodyNodes(BodyTreeParameterVo vo) {
        log.info("开始查询人体节点,查询条件: " + vo.toString());
        ListResult result = new ListResult();
        StopWatch stopWatch = StopWatch.createStarted();

        List<BodyTreeVo> list = new ArrayList<BodyTreeVo>();
        BodyTreeVo bodyTreeVo = new BodyTreeVo();
        List<Long> longList = new ArrayList<Long>();
        try {

            //根据根节点的本体的soid，查询局部解剖学下部位的本体soid
            List<Long> listSoid = new ArrayList<>();
            listSoid.add(vo.getNoumenonSoid());
            List<BodyTreeVo> listTmp = new ArrayList<BodyTreeVo>();
            ListResult<List<BodyTreeVo>> tmp = knwReportApi.getBodyTree(listSoid);
            listTmp = tmp.getData();

            if (listTmp != null && listTmp.size() > 0) {
                // 获取本体关系是 【is a part of】概念soid、如果取得的概念列表为空，返回提示信息
                if (DocFastWriteUtil.setConceptualSoidList(result, longList, listTmp)) {
                    return result;
                }

                // 设置人体树结构子节点相关属性
                setBodyTreeVo(vo, list, longList, listTmp);
            }

            buildListSuccess(result, list);
        } catch (Exception e) {
            list = new ArrayList<BodyTreeVo>();
            log.error("人体节点异常", e);
            buildListWarn(result, "查询人体节点失败,请联系管理员");
        } finally {
            stopWatch.stop();
            log.info("本次查询耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }


    /**
     * 获取人体图列表
     *
     * @param vo
     * @return
     * @throws Exception
     */
    @Override
    public ListResult getBodyMaps(com.mida.dms.knw.vo.PatientInfoParameterVo vo) {
        log.info("开始获取人体树结构,查询条件: " + vo.toString());
        ListResult result = new ListResult();
        StopWatch stopWatch = StopWatch.createStarted();

        List<BodyTreeVo> list = new ArrayList<BodyTreeVo>();
        BodyTreeVo bodyTreeVo = new BodyTreeVo();
        List<Long> longList = new ArrayList<>();
        MediaImageFindDto mediaImageFindDto = new MediaImageFindDto();
        try {
            List<MsdDataSet> listDataSet = new ArrayList<>();
            List<Long> conceptSoids = new ArrayList<Long>();

            // 验证部位soid
            if (DocFastWriteUtil.checkBodySoid(vo, result)) {
                return result;
            }

            // 根据部位的soid获取概念soid
            if (gainBodyConceptSoids(vo, result, conceptSoids)) {
                return result;
            }

            // 验证概念soid是否为空
            if (DocFastWriteUtil.checkConceptSoids(result, conceptSoids)) {
                return result;
            }



            // 验证本体
            List<KnwNoumenonVo> knwNoumenonVos = checkKnwNoumenonVo(result, conceptSoids);
            if (ObjectUtils.isEmpty(knwNoumenonVos)) {
                return result;
            }

            List<Long> conceptualSoids = new ArrayList<>();
            List<Long> noumenonSoidsTmp = new ArrayList<>();
            // 获取概念soidlist
            gainNoumenonSoidsList(knwNoumenonVos, conceptualSoids, noumenonSoidsTmp);

            // 根据概念列表获取、集值soid
            List<Long> lists = gainDataSetSoid(vo, mediaImageFindDto, conceptualSoids);

            Map<String, Object> map = new HashMap<String, Object>();
            // 设置集值map
            if (setDataSetSoidMap(vo, result, lists, map)) {
                return result;
            }

            // 设置图片对象
            BodyPictureVo bodyPictureVo = setBodyPictureVo(mediaImageFindDto, map);

            buildListSuccess(result, bodyPictureVo);
        } catch (Exception e) {
            list = new ArrayList<BodyTreeVo>();
            log.error("获取人体树结构异常", e);
            buildListWarn(result, "获取人体树结构失败,请联系管理员");
        } finally {
            stopWatch.stop();
            log.info("本次查询耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }


    /**
     * 取得推荐诊断列表
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult getRecommendDiagnosticList(com.mida.dms.knw.vo.PatientInfoParameterVo vo) {
        log.info("取得推荐诊断列表,查询条件: " + vo.toString());
        ListResult result = new ListResult();
        StopWatch stopWatch = StopWatch.createStarted();
        Map<String, Object> map = new HashMap<String, Object>();
        List<KnwIndividualSoltVos> list = new ArrayList();
        Map<Long, Object> mapTmp = new HashMap<Long, Object>();
        List<RecommendDiagnosticVo> listRecommendDiagnosticVo;
        RecommendDiagnosticVo recommendDiagnosticVo;
        try {
            listRecommendDiagnosticVo = gainRecommendDiagnosticVos(vo, map, mapTmp);

            buildListSuccess(result, listRecommendDiagnosticVo);
        } catch (Exception e) {
            list = new ArrayList<KnwIndividualSoltVos>();
            log.error("取得推荐诊断列表异常", e);
            buildListWarn(result, "取得推荐诊断列表失败,请联系管理员");
        } finally {
            stopWatch.stop();
            log.info("本次查询耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }


    /**
     * 根据部位soid、检查类型soid查询相关领域本体的soid
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult getNoumenonDomainSoids(com.mida.dms.knw.vo.PatientInfoParameterVo vo) {
        log.info("根据部位soid、检查类型soid查询相关领域本体的soid,查询条件: " + vo.toString());
        ListResult result = new ListResult();
        StopWatch stopWatch = StopWatch.createStarted();
        List<Long> longList = new ArrayList<>();
        StringBuffer strBuff = new StringBuffer();
        try {
            String[] str;
            List<MsdDataSet> listDataSet = new ArrayList<>();
            List<Long> conceptSoids = new ArrayList<Long>();
            List<Long> conceptualSoids = new ArrayList<Long>();

            // 根据部位、获取概念soid
            if (gainConceptSoids(vo, result, strBuff, conceptSoids)) {return result;}

            // 根据概念soid、获取相关本体对应的概念soid
            gainConceptSoids(conceptualSoids, conceptSoids);

            // 设置相关领域本体的soid
            setNoumenonSoid(vo, strBuff, conceptualSoids);

            buildListSuccess(result, strBuff);
        } catch (Exception e) {
            log.error("根据部位soid、检查类型soid查询相关领域本体的soid异常", e);
            buildListWarn(result, "根据部位、检查类型查询相关领域本体失败,请联系管理员");
        } finally {
            stopWatch.stop();
            log.info("本次查询耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }


    /**
     * 1.查询所有本体
     *
     * @param search
     * @return
     */
    @Override
    public ListResult<List<KnwNoumenonVo>> findAll(String search) throws Exception {

        // 查询所有本体
        ListResult result = new ListResult();
        ListResult<List<KnwNoumenonVo>> resultTmp = knwReportApi.findAll(search);

        Map<Long, Long> mapDataSetSoid = new HashMap<>();
        if (resultTmp != null && resultTmp.getData() != null) {
            List<KnwNoumenonVo> list = resultTmp.getData();
            List<Long> listTmp = new ArrayList<Long>();
            if (list != null && list.size() > 0) {
                list.stream().forEach(a -> {
                    if (ObjectUtils.isNotEmpty(a.getNoumenonSubType())) {
                        if (mapDataSetSoid.get(a.getNoumenonSubType()) == null) {
                            mapDataSetSoid.put(a.getNoumenonSubType(), a.getNoumenonSubType());
                        }
                    }
                });

                // 根据值soid获取对应集值对象
                listTmp = mapDataSetSoid.values().stream()
                        .collect(Collectors.toList());
                Map<Long, String> mapDataSetName =
                        detailCodingSystemService.getDataSetNameMap(listTmp);

                // 设置名字
                list.stream().forEach(a -> {
                    a.setNoumenonSubTypeName(mapDataSetName.get(a.getNoumenonSubType()));
                });
            }

        }

        return result;
    }

    /**
     * 3.根据本体soid查询所有本体Slot
     *
     * @param noumenonSoid
     * @return
     */
    @Override
    public ListResult<List<KnwSlotVo>> findAllSoltBynoumenonSoid(Long noumenonSoid) throws Exception {
        // 根据本体soid查询所有本体Slot
        ListResult<List<KnwSlotVo>> result =
                knwReportApi.findAllSoltBynoumenonSoid(noumenonSoid);

        if (result != null && result.getData() != null) {
            List<KnwSlotVo> list = result.getData();

            // 取得所有集值soid列表、以及编码体系soid列表
            Map<Long, Long> mapDataSetSoid = new HashMap<>();
            Map<Long, Long> mapDetailCodingSystemSoid = new HashMap<>();
            List<Long> listTmp = new ArrayList<Long>();
            // 设置值集map和编码体系map
            DocFastWriteUtil.setDsMapAndDcsMap(list, mapDataSetSoid, mapDetailCodingSystemSoid);

            // 根据值soid获取对应集值对象
            setKnwSlotVo(list, mapDataSetSoid, mapDetailCodingSystemSoid);
        }


        return result;
    }

    /**
     * 2.分页查询本体
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult<PageResultVo<KnwNoumenonVo>> findPage(KnwNoumenonPageVo vo)
            throws Exception {
        ListResult result = new ListResult();
        ListResult<PageResultVo<KnwNoumenonVo>> resultTmp =
                knwReportApi.findPage(vo);

        if (resultTmp != null && resultTmp.getData() != null) {
            PageResultVo<KnwNoumenonVo> pageResultVo = resultTmp.getData();
            List<KnwNoumenonVo> list = pageResultVo.getList();

            if (list != null && list.size() > 0) {
                // 取得所有集值soid列表、以及编码体系soid列表
                Map<Long, Long> mapDataSetSoid = new HashMap<>();
                Map<Long, Long> mapDetailCodingSystemSoid = new HashMap<>();
                List<Long> listTmp = new ArrayList<Long>();

                // 获取值集SOID的MAP和编码体系soid的MAP
                DocFastWriteUtil.gainDsMapSoidAndDcsMapSoid(list, mapDataSetSoid, mapDetailCodingSystemSoid);

                // 根据值soid获取对应集值对象、编码体系对象并进行设置相关对象属性对应的名称
                setKnwNoumenonVoPropertyName(list, mapDataSetSoid, mapDetailCodingSystemSoid);
                buildListSuccess(result, list);
            }
        }

        return result;
    }

    /**
     * 4.根据本体soid分页查询slot
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult<PageResultVo<KnwSlotVo>> findPageSlotBynoumenonSoid(KnwSlotPageVo vo)
            throws Exception {
        ListResult result = new ListResult();
        // 根据本体soid分页查询slot
        ListResult<PageResultVo<KnwSlotVo>> resultTmp =
                knwReportApi.findPageSlotBynoumenonSoid(vo);

        PageResultVo<KnwSlotVo> pageResultVo = new PageResultVo<KnwSlotVo>();
        if (resultTmp != null && resultTmp.getData() != null) {
            pageResultVo = resultTmp.getData();
            List<KnwSlotVo> list = pageResultVo.getList();

            // 取得所有集值soid列表、以及编码体系soid列表
            Map<Long, Long> mapDataSetSoid = new HashMap<>();
            Map<Long, Long> mapDetailCodingSystemSoid = new HashMap<>();
            List<Long> listTmp = new ArrayList<Long>();
            // 设置值集map和编码体系map
            DocFastWriteUtil.setDsMapAndDcsMap(list, mapDataSetSoid, mapDetailCodingSystemSoid);

            // 设置本体slot相关属性名称
            setKnwSlotVo(list, mapDataSetSoid, mapDetailCodingSystemSoid);
            buildListSuccess(result, pageResultVo);
        }
        return result;
    }


    /**
     * 5.根据本体soid获取本体
     *
     * @param soid
     * @return
     */
    @Override
    public ListResult<KnwNoumenonVo> gainKnwNoumenon(Long soid) throws Exception {
        ListResult result = new ListResult();
        // 根据本体soid获取本体
        ListResult<KnwNoumenonVo> resultTmp = knwReportApi.get(soid);
        if (resultTmp != null && resultTmp.getData() != null) {
            KnwNoumenonVo vo = resultTmp.getData();

            Map<Long, Long> mapDataSetSoid = new HashMap<>();
            Map<Long, Long> mapDetailCodingSystemSoid = new HashMap<>();
            List<Long> listTmp = new ArrayList<Long>();
            // 设置值集map和编码体系map
            DocFastWriteUtil.setDsMapAndDcsMap(vo, mapDataSetSoid, mapDetailCodingSystemSoid);

            // 根据值soid获取对应集值对象
            setKnwNoumenonVo(vo, mapDataSetSoid, mapDetailCodingSystemSoid);
            buildListSuccess(result, vo);
        }
        return result;
    }


    /**
     * 6.根据slotSoid查询slot
     *
     * @param soid
     * @return
     */
    @Override
    public ListResult<KnwSlotVo> findSlotBySlotSoid(Long soid) throws Exception {
        // 根据slotSoid查询slot
        ListResult<KnwSlotVo> result = knwReportApi.findSlotBySlotSoid(soid);
        if (result != null && result.getData() != null) {
            KnwSlotVo knwSlotVo = result.getData();
        }
        return result;
    }


    /**
     * 设置本体slot相关属性名称
     *
     * @param list
     * @param mapDataSetSoid
     * @param mapDetailCodingSystemSoid
     * @throws Exception
     */
    private void setKnwSlotVo(List<KnwSlotVo> list,
                              Map<Long, Long> mapDataSetSoid,
                              Map<Long, Long> mapDetailCodingSystemSoid) throws Exception {
        List<Long> listTmp;
        listTmp = mapDataSetSoid.values().stream()
                .collect(Collectors.toList());
        Map<Long, MsdDataSet> mapDataSetName =
                detailCodingSystemService.getDataSetMap(listTmp);

        listTmp = new ArrayList<Long>();
        listTmp = mapDetailCodingSystemSoid.values().stream()
                .collect(Collectors.toList());

        // 根据编码体系soid获取对应编码体系对象
        Map<Long, MsdDetailCodingSystem> mapDetailCodingSystemName =
                detailCodingSystemService.getDetailCodingSystemNameMap(listTmp);

        // 设置对象
        list.stream().forEach(b -> {
            MsdDataSet msdDataSetTmp;
            if (mapDataSetName.get(b.getDataType()) != null) {
                msdDataSetTmp = mapDataSetName.get(b.getDataType());
                b.setDataSetMeaning(msdDataSetTmp.getDataSetMeaning());
            }
            if (mapDataSetName.get(b.getUnit()) != null) {
                msdDataSetTmp = mapDataSetName.get(b.getUnit());
                b.setUnitName(msdDataSetTmp.getDataSetMeaning());
                b.setUnitDescription(msdDataSetTmp.getDataSetDescription());
            }
            MsdDetailCodingSystem m;
            if (mapDetailCodingSystemName.get(b.getDerailCodingSystemSoid()) != null) {
                m = mapDetailCodingSystemName.get(b.getDerailCodingSystemSoid());
                b.setDerailCodingSystemName(m.getCnName());
            }
        });
    }

    /**
     * 根据部位的soid获取概念soid
     *
     * @param vo
     * @param result
     * @param conceptSoids
     * @return
     * @throws Exception
     */
    private boolean gainBodyConceptSoids(
            com.mida.dms.knw.vo.PatientInfoParameterVo vo,
            ListResult result, List<Long> conceptSoids) throws Exception {
        String[] str;
        List<MsdDataSet> listDataSet;
        str = vo.getBodySoid().split(COMMA);
        List<String> lists = Arrays.asList(str);
        List<Long> lList = new ArrayList<Long>();
        for (String s : lists) {
            lList.add(Long.valueOf(s));
        }
        // 根据部位的soid获取概念soid
        listDataSet = detailCodingSystemService.getConceptSoidsByDataSetSoids(lList);

        if (listDataSet != null && listDataSet.size() > 0) {
            for (MsdDataSet d : listDataSet) {
                if (d.getConceptSoid() != null) {
                    conceptSoids.add(d.getConceptSoid());
                }
            }

            if (conceptSoids.size() == 0) {
                buildListWarn(result, WARN_MESSAGE_0001);
                return true;
            }
        }
        return false;
    }

    /**
     * 根据部位、获取概念soid
     *
     * @param vo
     * @param result
     * @param strBuff
     * @param conceptSoids
     * @return
     * @throws Exception
     */
    private boolean gainConceptSoids(com.mida.dms.knw.vo.PatientInfoParameterVo vo,
                                     ListResult result, StringBuffer strBuff,
                                     List<Long> conceptSoids) throws Exception {
        String[] str;
        List<MsdDataSet> listDataSet;
        if (StringUtils.isNotEmpty(vo.getBodySoid())) {
            str = vo.getBodySoid().split(COMMA);
            List<String> lists = Arrays.asList(str);
            List<Long> lList = new ArrayList<Long>();
            for (String s : lists) {
                lList.add(Long.valueOf(s));
            }

            listDataSet = detailCodingSystemService.getConceptSoidsByDataSetSoids(lList);

            if (listDataSet != null && listDataSet.size() > 0) {
                for (MsdDataSet d : listDataSet) {
                    if (d.getConceptSoid() != null) {
                        conceptSoids.add(d.getConceptSoid());
                    }
                }
                if (conceptSoids.size() == 0) {
                    buildListSuccess(result, strBuff);
                    return true;
                }
            }
        }
        return false;
    }


    /**
     * 获取诊断内容
     *
     * @param vo
     * @param map
     * @param mapTmp
     * @return
     */
    @NotNull
    private List<RecommendDiagnosticVo> gainRecommendDiagnosticVos(
            com.mida.dms.knw.vo.PatientInfoParameterVo vo, Map<String, Object> map,
            Map<Long, Object> mapTmp) {
        List<KnwIndividualSoltVos> list;
        List<RecommendDiagnosticVo> listRecommendDiagnosticVo;
        RecommendDiagnosticVo recommendDiagnosticVo;
        List<String> listDataSetSoid = new ArrayList<String>();
        if (StringUtils.isNotEmpty(vo.getBodySoid())) {
            String[] bodySoids = vo.getBodySoid().split(COMMA);
            listDataSetSoid = Arrays.stream(bodySoids).collect(Collectors.toList());
            map.put("list", listDataSetSoid);
        }

        ListResult<List<KnwIndividualSoltVos>> tmp = knwReportApi.getRecommendDiagnosticList(map);
        list = tmp.getData();

        List<KnwIndividualSoltVos> listTmp;
        for (KnwIndividualSoltVos ksv : list) {
            listTmp = new ArrayList<>();
            KnwIndividualSoltVos knwSlotVo = new KnwIndividualSoltVos();
            knwSlotVo = ksv;
            if (mapTmp.get(ksv.getIndividualSoid()) == null) {
                listTmp.add(knwSlotVo);
                mapTmp.put(ksv.getIndividualSoid(), listTmp);
            } else {
                listTmp = (List<KnwIndividualSoltVos>) mapTmp.get(ksv.getIndividualSoid());
                listTmp.add(knwSlotVo);
                mapTmp.put(ksv.getIndividualSoid(), listTmp);
            }
        }

        Map<String, Object> mapExamServiceType = new HashMap<String, Object>();
        if (StringUtils.isNotEmpty(vo.getExamServiceTypeSoid())) {
            String[] strs = vo.getExamServiceTypeSoid().split(COMMA);
            for (String str : strs) {
                if (StringUtils.isNotEmpty(str)) {
                    mapExamServiceType.put(str, str);
                }
            }
        }

        // 设置诊断内容
        listRecommendDiagnosticVo = new ArrayList<>();
        DocFastWriteUtil.setRecommendDiagnosticVo(vo, mapTmp, listRecommendDiagnosticVo, mapExamServiceType);
        return listRecommendDiagnosticVo;
    }


    /**
     * 设置本体对象
     *
     * @param vo
     * @param mapDataSetSoid
     * @param mapDetailCodingSystemSoid
     * @throws Exception
     */
    private void setKnwNoumenonVo(KnwNoumenonVo vo,
                                  Map<Long, Long> mapDataSetSoid,
                                  Map<Long, Long> mapDetailCodingSystemSoid) throws Exception {
        List<Long> listTmp;
        listTmp = mapDataSetSoid.values().stream()
                .collect(Collectors.toList());
        Map<Long, MsdDataSet> mapDataSetName = detailCodingSystemService.getDataSetMap(listTmp);

        // 根据编码体系soid获取对应编码体系对象
        listTmp = new ArrayList<Long>();
        listTmp = mapDetailCodingSystemSoid.values().stream()
                .collect(Collectors.toList());

        Map<Long, MsdDetailCodingSystem> mapDetailCodingSystemName =
                detailCodingSystemService.getDetailCodingSystemNameMap(listTmp);

        MsdDataSet msdDataSet;
        if (mapDataSetName.get(vo.getNoumenonType()) != null) {
            msdDataSet = mapDataSetName.get(vo.getNoumenonType());
            vo.setNoumenonTypeName(msdDataSet.getDataSetMeaning());
        }

        if (mapDataSetName.get(vo.getNoumenonSubType()) != null) {
            msdDataSet = mapDataSetName.get(vo.getNoumenonSubType());
            vo.setNoumenonSubTypeName(msdDataSet.getDataSetMeaning());
        }

        vo.setPageTypeName(vo.getNoumenonTypeName()
                + LONG_STRING + vo.getNoumenonSubTypeName());
        // 设置对象
        vo.getListKnwSlotVo().stream().forEach(b -> {
            MsdDataSet msdDataSetTmp;
            if (mapDataSetName.get(b.getDataType()) != null) {
                msdDataSetTmp = mapDataSetName.get(b.getDataType());
                b.setDataSetMeaning(msdDataSetTmp.getDataSetMeaning());
            }
            if (mapDataSetName.get(b.getUnit()) != null) {
                msdDataSetTmp = mapDataSetName.get(b.getUnit());
                b.setUnitName(msdDataSetTmp.getDataSetMeaning());
                b.setUnitDescription(msdDataSetTmp.getDataSetDescription());
            }

            MsdDetailCodingSystem m;
            if (mapDetailCodingSystemName.get(b.getDerailCodingSystemSoid()) != null) {
                m = mapDetailCodingSystemName.get(b.getDerailCodingSystemSoid());
                b.setDerailCodingSystemName(m.getCnName());
            }
        });
    }

    /**
     * 验证本体
     *
     * @param result

     * @return
     */
    private List<KnwNoumenonVo> checkKnwNoumenonVo(ListResult result,List<Long> conceptSoids) {
        List<KnwNoumenonVo> knwNoumenonVos = new ArrayList<KnwNoumenonVo>();
        // 根据概念查询本体
        ListResult<List<KnwNoumenonVo>> tmpKnwNoumenonVo = knwReportApi.getKnwNoumenons(conceptSoids);
        knwNoumenonVos = tmpKnwNoumenonVo.getData();
        if (knwNoumenonVos == null || knwNoumenonVos.size() == 0) {
            buildListWarn(result, ERROR_MESSAGE_0003);
            return null;
        }
        return knwNoumenonVos;
    }

    /**
     * @param noumenonSoidsTmp
     * @param listTmp
     * @return
     */
    private List<BodyTreeVo> gainBodyTreeVos(List<Long> noumenonSoidsTmp, List<BodyTreeVo> listTmp) {
        if (noumenonSoidsTmp.size() > 0) {
            ListResult<List<BodyTreeVo>> tmp = knwReportApi.getBodyTree(noumenonSoidsTmp);
            listTmp = tmp.getData();
        }

        if (listTmp == null || listTmp.size() == 0) {
            return null;
        }
        return listTmp;
    }


    /**
     * 根据概念列表获取、集值soid
     *
     * @param vo
     * @param mediaImageFindDto
     * @param conceptualSoids
     * @return
     * @throws Exception
     */
    private List<Long> gainDataSetSoid(com.mida.dms.knw.vo.PatientInfoParameterVo vo, MediaImageFindDto mediaImageFindDto, List<Long> conceptualSoids) throws Exception {
        List<Long> lists = new ArrayList<>();
        if (conceptualSoids != null && conceptualSoids.size() > 0) {
            lists = detailCodingSystemService.getDataSetSoidsByConceptSoids(conceptualSoids);
        }

        String strs = "";
        if (lists != null && lists.size() > 0) {
            for (int i = 0; i < lists.size(); i++) {
                if (i == 0) {
                    strs = vo.getBodySoid() + COMMA + String.valueOf(lists.get(i));
                } else {
                    strs += COMMA + String.valueOf(lists.get(i));
                }
            }
        }

        // 获取部位
        mediaImageFindDto.setAge(vo.getAge());
        mediaImageFindDto.setGenderSoid(vo.getSexSoid());
        mediaImageFindDto.setBodyPartSoid(strs);
        return lists;
    }


    /**
     * 设置集值map
     *
     * @param vo
     * @param result
     * @param lists
     * @param map
     * @return
     * @throws Exception
     */
    private boolean setDataSetSoidMap(com.mida.dms.knw.vo.PatientInfoParameterVo vo, ListResult result, List<Long> lists, Map<String, Object> map) throws Exception {
        List<MsdDataSet> listDataSet;
        listDataSet = new ArrayList<>();
        listDataSet = detailCodingSystemService.getConceptSoidsByDataSetSoids(lists);

        List<Long> conceptSoidTmps = new ArrayList<>();
        if (listDataSet != null && listDataSet.size() > 0) {
            for (MsdDataSet d : listDataSet) {
                if (d.getConceptSoid() != null) {
                    conceptSoidTmps.add(d.getConceptSoid());
                }
            }
            if (conceptSoidTmps.size() == 0) {
                buildListWarn(result, WARN_MESSAGE_0001);
                return true;
            }
        }

        Map<String, Object> mapParm = new HashMap<String, Object>();
        mapParm.put("listConceptualSoid", conceptSoidTmps);
        mapParm.put("type", vo.getExamServiceTypeSoid());
        // 根据服务实例soid以及概念soid查询，相关领域本体下对应服务实例类型的本体soid
        List<KnwNoumenonVo> listKnwNoumenonVo = new ArrayList<>();
        //commonknwNoumenonMapper.getKnwNoumenonList(mapParm);
        ListResult<List<KnwNoumenonVo>> tmp = knwReportApi.getKnwNoumenonList(mapParm);
        listKnwNoumenonVo = tmp.getData();

        if (listKnwNoumenonVo != null && listKnwNoumenonVo.size() > 0) {
            for (KnwNoumenonVo v : listKnwNoumenonVo) {
                List<Long> listTmp = new ArrayList<>();
                if (v.getConceptualSoid() != null) {
                    listTmp.add(v.getConceptualSoid());
                    lists = detailCodingSystemService.getDataSetSoidsByConceptSoids(listTmp);
                    if (lists != null && lists.size() > 0) {
                        for (Long s : lists) {
                            String dataSetSoid = String.valueOf(s);
                            if (map.get(dataSetSoid) == null) {
                                map.put(dataSetSoid, v.getNoumenonSoid());
                            } else {
                                String strSoid = (String) map.get(v.getNoumenonSoid());
                                strSoid += COMMA + String.valueOf(v.getNoumenonSoid());
                                map.put(dataSetSoid, strSoid);
                            }
                        }
                    }
                }
            }
        }
        return false;
    }


    /**
     * 设置图片对象
     *
     * @param mediaImageFindDto
     * @param map
     * @return
     */
    private BodyPictureVo setBodyPictureVo(MediaImageFindDto mediaImageFindDto, Map<String, Object> map) {
        List<PictureVo> listPictureVo = new ArrayList<>();
        PictureVo pictureVo = new PictureVo();
        BodyPictureVo bodyPictureVo = new BodyPictureVo();
        // 根据所有部位soid，年龄soid、性别soid获取图列表
        ListResult<List<MediaImageResourceVo>> listResult
                = iResourceInfoApi.findByPatientInfo(mediaImageFindDto);

        if (listResult != null
                && listResult.getData() != null
                && listResult.getData().size() > 0) {
            List<MediaImageResourceVo> listMediaImageResourceVo = listResult.getData();
            for (int i = 0; i < listMediaImageResourceVo.size(); i++) {
                if (i == 0) {
                    BeanUtils.copyProperties(listMediaImageResourceVo.get(0), bodyPictureVo);
                } else {
                    pictureVo = new PictureVo();
                    BeanUtils.copyProperties(listMediaImageResourceVo.get(i), pictureVo);
                    listPictureVo.add(pictureVo);
                }
            }

            for (PictureVo pv : listPictureVo) {
                if (map.get(pv.getBodyPart()) != null) {
                    pv.setRelatedSoids(map.get(pv.getBodyPart()).toString());
                }
            }

            bodyPictureVo.setList(listPictureVo);

        }
        return bodyPictureVo;
    }

    /**
     * 设置人体树结构子节点相关属性
     *
     * @param vo
     * @param list
     * @param longList
     * @param listTmp
     */
    private void setBodyTreeVo(BodyTreeParameterVo vo,
                               List<BodyTreeVo> list,
                               List<Long> longList,
                               List<BodyTreeVo> listTmp) {
        BodyTreeVo bodyTreeVo;
        Map<String, Object> mapParm = new HashMap<String, Object>();
        mapParm.put("listConceptualSoid", longList);
        mapParm.put("type", vo.getExamServiceTypeSoid());
        StringBuffer str = new StringBuffer();
        // 根据本体类型soid以及概念soid查询，相关领域本体下对应本体类型的本体soid
        List<KnwNoumenonVo> listKnwNoumenonVo = new ArrayList<>();
        ListResult<List<KnwNoumenonVo>> tmpList = knwReportApi.getKnwNoumenonList(mapParm);
        listKnwNoumenonVo = tmpList.getData();

        Map<Long, Object> map = new HashMap<Long, Object>();
        Map<Long, Long> mapBodySoid = new HashMap<Long, Long>();
        if (listKnwNoumenonVo != null && listKnwNoumenonVo.size() > 0) {
            for (KnwNoumenonVo v : listKnwNoumenonVo) {
                if (map.get(v.getConceptualSoid()) == null) {
                    map.put(v.getConceptualSoid(), v.getNoumenonSoid());
                } else {
                    String strSoid = (String) map.get(v.getNoumenonSoid());
                    strSoid += COMMA + String.valueOf(v.getNoumenonSoid());
                    map.put(v.getConceptualSoid(), strSoid);
                }

                if (mapBodySoid.get(v.getConceptualSoid()) == null) {
                    mapBodySoid.put(v.getConceptualSoid(), v.getDataSetSoid());
                }
            }
        }
        //设置返回对象
        DocFastWriteUtil.setBodyTreeVoList(list, listTmp, map, mapBodySoid);
    }


    /**
     * 根据检查部位下、部位soid获取对应概念soid、设置map
     *
     * @param strs
     * @param listConceptSoid
     * @param mapBodySoid
     * @throws Exception
     */
    private void gainBodyConceptSoid(String[] strs,
                                     List<Long> listConceptSoid,
                                     Map<Long, Object> mapBodySoid) throws Exception {
        for (String str : strs) {
            if (StringUtils.isNotEmpty(str)) {
                MsdDataSet msdDataSet =
                        detailCodingSystemService.getConceptSoidByDataSetSoid(
                                Long.valueOf(str));

                if (msdDataSet != null && ObjectUtils.isNotEmpty(msdDataSet.getConceptSoid())) {
                    listConceptSoid.add(msdDataSet.getConceptSoid());
                    mapBodySoid.put(msdDataSet.getConceptSoid(), Long.valueOf(str));
                }
            }
        }
    }

    /**
     * 设置人体树结构相关属性
     *
     * @param vo
     * @param list
     * @param listConceptSoid
     * @param mapBodySoid
     */
    private void setBodyTreeVo(BodyTreeParameterVo vo,
                               List<BodyTreeVo> list,
                               List<Long> listConceptSoid,
                               Map<Long, Object> mapBodySoid) {
        BodyTreeVo bodyTreeVo;
        // // 概念列表不为空的场合
        if (listConceptSoid != null && listConceptSoid.size() > 0) {
            for (Long conceptSoid : listConceptSoid) {

                if (conceptSoid == null) {
                    continue;
                }
                // 根据概念soid取得 局部解剖学下部位的本体soid
                KnwNoumenonVo knwNoumenonVo = new KnwNoumenonVo();
                ListResult<KnwNoumenonVo> tmp = knwReportApi.getKnwNoumenonByConceptSoid(conceptSoid);
                knwNoumenonVo = tmp.getData();
                if (knwNoumenonVo != null) {
                    Map<String, Object> mapTmp = new HashMap<String, Object>();
                    List<Long> listTmp = new ArrayList<>();
                    listTmp.add(conceptSoid);
                    mapTmp.put("listConceptualSoid", listTmp);
                    mapTmp.put("type", vo.getExamServiceTypeSoid());
                    StringBuffer str = new StringBuffer();
                    // 本体类型soid以及概念soid查询，相关领域本体下对应本体类型的本体soid
                    List<KnwNoumenonVo> listKnwNoumenonVo = new ArrayList<KnwNoumenonVo>(); //= commonknwNoumenonMapper.getKnwNoumenonList(mapTmp);
                    ListResult<List<KnwNoumenonVo>> tmpList = knwReportApi.getKnwNoumenonList(mapTmp);
                    listKnwNoumenonVo = tmpList.getData();

                    if (listKnwNoumenonVo != null && listKnwNoumenonVo.size() > 0) {
                        for (int i = 0; i < listKnwNoumenonVo.size(); i++) {
                            if (i == 0) {
                                str.append(listKnwNoumenonVo.get(i).getNoumenonSoid());
                            } else {
                                str.append(COMMA);
                                str.append(listKnwNoumenonVo.get(i).getNoumenonSoid());
                            }
                        }
                    }

                    bodyTreeVo = new BodyTreeVo();
                    bodyTreeVo.setNoumenonShowName(knwNoumenonVo.getNoumenonShowName());
                    bodyTreeVo.setNoumenonSoid(knwNoumenonVo.getNoumenonSoid());
                    bodyTreeVo.setRelatedSoids(str.toString());
                    bodyTreeVo.setCnt(knwNoumenonVo.getCnt());
                    if (mapBodySoid.get(knwNoumenonVo.getConceptualSoid()) != null) {
                        bodyTreeVo.setBodySoid((Long) mapBodySoid.get(knwNoumenonVo.getConceptualSoid()));
                    }
                    list.add(bodyTreeVo);
                }
            }
        }
    }

    /**
     * 根据值soid获取对应集值对象、编码体系对象并进行设置相关对象属性对应的名称
     *
     * @param list
     * @param mapDataSetSoid
     * @param mapDetailCodingSystemSoid
     * @throws Exception
     */
    private void setKnwNoumenonVoPropertyName(
            List<KnwNoumenonVo> list,
            Map<Long, Long> mapDataSetSoid,
            Map<Long, Long> mapDetailCodingSystemSoid) throws Exception {
        List<Long> listTmp;// 根据值soid获取对应集值对象
        listTmp = mapDataSetSoid.values().stream()
                .collect(Collectors.toList());
        Map<Long, MsdDataSet> mapDataSetName =
                detailCodingSystemService.getDataSetMap(listTmp);

        listTmp = new ArrayList<Long>();
        listTmp = mapDetailCodingSystemSoid.values().stream()
                .collect(Collectors.toList());

        // 根据编码体系soid获取对应编码体系对象
        Map<Long, MsdDetailCodingSystem> mapDetailCodingSystemName =
                detailCodingSystemService.getDetailCodingSystemNameMap(listTmp);

        // 设置对象
        DocFastWriteUtil.setKnwNoumenonVo(list, mapDataSetName, mapDetailCodingSystemName);
    }

    /**
     * 设置相关领域本体的soid
     *
     * @param vo
     * @param strBuff
     * @param conceptualSoids
     * @throws Exception
     */
    private void setNoumenonSoid(com.mida.dms.knw.vo.PatientInfoParameterVo vo,
                                 StringBuffer strBuff,
                                 List<Long> conceptualSoids) throws Exception {
        List<Long> lists = new ArrayList<>();
        if (conceptualSoids != null && conceptualSoids.size() > 0) {
            lists = detailCodingSystemService.getDataSetSoidsByConceptSoids(conceptualSoids);

            Map<String, Object> mapParm = new HashMap<String, Object>();
            mapParm.put("listConceptualSoid", conceptualSoids);
            mapParm.put("type", vo.getExamServiceTypeSoid());
            // 根据服务实例soid以及概念soid查询，相关领域本体下对应服务实例类型的本体soid
            List<KnwNoumenonVo> listKnwNoumenonVo = new ArrayList<>();
            ListResult<List<KnwNoumenonVo>> tmp = knwReportApi.getKnwNoumenonList(mapParm);
            listKnwNoumenonVo = tmp.getData();
            Map<String, Object> map = new HashMap<String, Object>();
            if (listKnwNoumenonVo != null && listKnwNoumenonVo.size() > 0) {
                for (int i = 0; i < listKnwNoumenonVo.size(); i++) {
                    if (i == 0) {
                        strBuff.append(listKnwNoumenonVo.get(i).getNoumenonSoid());
                    } else {
                        strBuff.append(COMMA);
                        strBuff.append(listKnwNoumenonVo.get(i).getNoumenonSoid());
                    }
                }
            }
        }
    }


    /**
     * 根据概念soid、获取相关本体对应的概念soid
     *
     * @param conceptualSoids
     * @param conceptSoids
     */
    private void gainConceptSoids(List<Long> conceptualSoids, List<Long> conceptSoids) {
        List<KnwNoumenonVo> knwNoumenonVos = new ArrayList<KnwNoumenonVo>();

        if (conceptSoids == null || conceptSoids.size() == 0) {
            return;
        }

        List<Long> noumenonSoidsTmp = new ArrayList<>();

        if (addConceptualSoidsAndNoumenonSoidsTmp(
                conceptSoids, conceptualSoids, noumenonSoidsTmp)) {
            return;
        }


        // 根据本体soid列表获取本体对应的概念、已经本体下的本性关系对应本体的soid
        List<BodyTreeVo> listTmp = new ArrayList<>();
        listTmp = gainBodyTreeVos(noumenonSoidsTmp, listTmp);
        if (listTmp == null) {return;}
        noumenonSoidsTmp =  DocFastWriteUtil.addConceptualSoidsAndNoumenonSoidsTmp(conceptualSoids, listTmp);

        // 根据本体soid列表获取本体对应的概念、已经本体下的本性关系对应本体的soid
        listTmp = gainBodyTreeVos(noumenonSoidsTmp, listTmp);
        if (listTmp == null){return;}
        noumenonSoidsTmp =  DocFastWriteUtil.addConceptualSoidsAndNoumenonSoidsTmp(conceptualSoids, listTmp);

        // 根据本体soid列表获取本体对应的概念、已经本体下的本性关系对应本体的soid
        listTmp = gainBodyTreeVos(noumenonSoidsTmp, listTmp);
        if (listTmp == null) {return;}
        DocFastWriteUtil.addConceptualSoidsAndNoumenonSoidsTmp(conceptualSoids, listTmp);

    }

    /**
     * @param conceptSoids
     * @param conceptualSoids
     * @param noumenonSoidsTmp
     * @return
     */
    private boolean addConceptualSoidsAndNoumenonSoidsTmp(List<Long> conceptSoids,
                                                          List<Long> conceptualSoids,
                                                          List<Long> noumenonSoidsTmp) {
        List<KnwNoumenonVo> knwNoumenonVos;
        ListResult<List<KnwNoumenonVo>> tmp = knwReportApi.getKnwNoumenons(conceptSoids);
        knwNoumenonVos = tmp.getData();

        if (knwNoumenonVos == null || knwNoumenonVos.size() == 0) {
            return true;
        }

        for (KnwNoumenonVo v : knwNoumenonVos) {
            if (v.getConceptualSoid() != null) {
                conceptualSoids.add(v.getConceptualSoid());
            }
            if (v.getCnt() > 0) {
                if (v.getNoumenonSoid() != null) {
                    noumenonSoidsTmp.add(v.getNoumenonSoid());
                }
            }
        }
        return false;
    }


    /**
     * 获取概念soidlist
     *
     * @param knwNoumenonVos
     * @param conceptualSoids
     * @param noumenonSoidsTmp
     */
    private void gainNoumenonSoidsList(List<KnwNoumenonVo> knwNoumenonVos,
                                       List<Long> conceptualSoids, List<Long> noumenonSoidsTmp) {
        if (knwNoumenonVos == null || knwNoumenonVos.size() == 0) {
            return;
        }

        for (KnwNoumenonVo v : knwNoumenonVos) {
            if (v.getConceptualSoid() != null) {
                conceptualSoids.add(v.getConceptualSoid());
            }
            if (v.getCnt() > 0) {
                if (v.getNoumenonSoid() != null) {
                    noumenonSoidsTmp.add(v.getNoumenonSoid());
                }
            }
        }

        // 根据本体soid列表获取本体对应的概念、已经本体下的本性关系对应本体的soid
        List<BodyTreeVo> listTmp = new ArrayList<>();
        listTmp = gainBodyTreeVos(noumenonSoidsTmp, listTmp);
        if (listTmp == null) return;
        noumenonSoidsTmp = DocFastWriteUtil.addConceptualSoidsAndNoumenonSoidsTmp(conceptualSoids, listTmp);

        // 根据本体soid列表获取本体对应的概念、已经本体下的本性关系对应本体的soid
        listTmp = gainBodyTreeVos(noumenonSoidsTmp, listTmp);
        if (listTmp == null) return;
        noumenonSoidsTmp = DocFastWriteUtil.addConceptualSoidsAndNoumenonSoidsTmp(conceptualSoids, listTmp);

        // 根据本体soid列表获取本体对应的概念、已经本体下的本性关系对应本体的soid
        listTmp = gainBodyTreeVos(noumenonSoidsTmp, listTmp);
        if (listTmp == null) return;
        DocFastWriteUtil.addConceptualSoidsAndNoumenonSoidsTmp(conceptualSoids, listTmp);
    }
}
